<?php

/*
 * Title: hook.class.inc.php
 * Process events in the FoxyBack system and respond with custom handling, like 
 * interfacing with external systems.
 *
 */

include_once('config.inc.php');
include_once('atlast.class.inc.php');
include_once('foxyback.class.inc.php');
include_once('notify.class.inc.php');
include_once('webuser.class.inc.php');
include_once('includes/MailChimpUtils.php');

class Hook {

	// set class variables
	var $error_info = '';

	// Initialize the class
	function __construct()	{
	}

	// Trigger specific actions based on a system event.
	function ProcessEvent($event, $object, $object_id, $event_spec=array()) {
		global $modx, $STATUS_ARRAY, $WEB_GROUP_ARRAY;

		//print "process $event hook on $object $object_id\n";
		
		if (!$event || !$object || !$object_id) {
			print "missing parameter in ProcessEvent!\n";
			return NULL;
		}

		// Place custom handling in each section. The return value is not checked, 
		// so send an email if there is a problem!

		// =================================================================
		// A new customer was added.
		// =================================================================

		if ($object == 'customer' && $event == 'ADD') {
			$customer_id = $object_id;

			// Prepare to add a modx web user.
			// Get the customer and address information.
			$foxyback = new FoxyBack();

			$customer_view = $foxyback->getCustomerView($customer_id);
			$address_view = $foxyback->getAddressView($customer_view['address_id']);

			$add_spec = array(
				'username'	=> $customer_view['email'],
				'password' 	=> $customer_view['password'],
				'email'		=> $customer_view['email'],
				'fullname' 	=> $address_view['first_name'] . ' ' . $address_view['last_name'],
				'phone' 	=> $address_view['phone'],
				'country' 	=> $address_view['country'],
				'state' 	=> $address_view['state'],
				'zip' 		=> $customer_view['postal_code'],
			);

			// Add a modx web user
			$web_user_obj = new WebUser();
			if (!$web_user_id = $web_user_obj->addWebUser($add_spec)) {
				$this->error_info = 'Error adding web user: ' . $web_user_obj->error_info;
				return NULL;
			}
			else {
				// Save the web_user_id back to the customer.
				// Indicate that a hook should not be created since one is processing already.
				if (!$edit_id = $foxyback->editCustomer($customer_id, array('web_user_id' => $web_user_id), true)) {
					$this->error_info = 'Error editing the customer: ' . $foxyback->error_info;
					return NULL;
				}
			}
		}

		// =================================================================
		// A customer was edited.
		// =================================================================

		elseif ($object == 'customer' && $event == 'EDIT') {
			$customer_id = $object_id;

			// Prepare to edit a modx web user.
			$foxyback = new FoxyBack();

			$customer_view = $foxyback->getCustomerView($customer_id);

			$edit_spec = array(
				'username'	=> $customer_view['email'],
				'password' 	=> $customer_view['password'],
				'email'		=> $customer_view['email'],
			);

			// Make sure a webuser exists.
			$web_user_id = $customer_view['web_user_id'];
			
			$web_user_obj = new WebUser();

			if ($web_user_id > 0) {
				// Edit the modx web user.
				if (!$web_user_id = $web_user_obj->editWebUser($web_user_id, $edit_spec)) {
					$this->error_info = "Error editing webuser on customer $customer_id: " . $web_user_obj->error_info;
					return NULL;
				}
			}
			else {
				// Add this as a new user.
				// Get some additional fields.
				$address_view = $foxyback->getAddressView($customer_view['address_id']);

				$add_spec = array(
					'fullname' 	=> $address_view['first_name'] . ' ' . $address_view['last_name'],
					'phone' 	=> $address_view['phone'],
					'country' 	=> $address_view['country'],
					'state' 	=> $address_view['state'],
					'zip' 		=> $address_view['postal_code'],
				);
				// Combine with the spec from earlier.
				$add_spec = array_merge($add_spec, $edit_spec);

				// Add the user.
				if (!$web_user_id = $web_user_obj->addWebUser($add_spec)) {
					$this->error_info = "Error adding webuser on customer ($customer_id): " . $web_user_obj->error_info;
					return NULL;
				}
				else {
					// Save the web_user_id back to the customer.
					// Indicate that a hook should not be created since one is processing already.
					if (!$edit_id = $foxyback->editCustomer($customer_id, array('web_user_id' => $web_user_id), true)) {
						$this->error_info = "Error editing the customer ($customer_id): " . $foxyback->error_info;
						return NULL;
					}
				}
			}
		}

		// =================================================================
		// An address was edited.
		// =================================================================

		elseif ($object == 'address' && $event == 'EDIT') {
			$address_id = $object_id;

			// Prepare to edit a modx web user.
			// Get the customer and address information.
			$foxyback = new FoxyBack();

			$address_view = $foxyback->getAddressView($address_id);
			
			// Webuser info is tied to the primary billing address.
			$customer_id = $address_view['customer_id'];
			$customer_view = $foxyback->getCustomerView($customer_id);

			if ($address_id != $customer_view['address_id'] 
				|| $address_view['address_type'] != 'BILLING') {
				// Not the primary address.
				// Nothing further to process, so return.
				return 1;
			}

			$edit_spec = array(
				'fullname' 	=> $address_view['first_name'] . ' ' . $address_view['last_name'],
				'phone' 	=> $address_view['phone'],
				'country' 	=> $address_view['country'],
				'state' 	=> $address_view['state'],
				'zip' 		=> $address_view['postal_code'],
			);

			// Make sure a webuser exists.
			$web_user_id = $customer_view['web_user_id'];
			
			if ($web_user_id > 0) {
				// Edit the modx web user.
				$web_user_obj = new WebUser();
				$web_user_id = $web_user_obj->editWebUser($web_user_id, $edit_spec);
				if (!$web_user_id) {
					$this->error_info = "Error editing webuser on customer ($customer_id): " . $web_user_obj->error_info;
					return NULL;
				}
			}
			else {
				// A new web user needs to be added for this customer. 
				// Since the 'customer edit' hook already handles this, trigger an edit.
				if (!$edit_id = $foxyback->editCustomer($customer_id, array())) {
					$this->error_info = "Error editing the customer ($customer_id): " . $foxyback->error_info;
					return NULL;
				}
			}
		}

		// =================================================================
		// New transaction detail added.
		// =================================================================

		elseif ($object == 'transaction_detail' && $event == 'ADD') {
			// Most likely this is a datafeed import. 
			$foxyback = new FoxyBack();

			// Continue processing if it is an application.
			$detail_list = $event_spec;
			$transaction_id = $event_spec['transaction_id'];

			if ($detail_list['category_code'] == 'application') {
				if (!$transaction_view = $foxyback->getTransactionView($transaction_id)) {
					$this->error_info = "Error viewing transaction $transaction_id: " . $foxyback->error_info;
					return NULL;
				}
				
				// Adjust the transaction status to "application pending" if it currently has the default status.
				if ($transaction_view['order_status_id'] == $STATUS_ARRAY['New']) {	
					// Adjust.
					if (!$edit_transaction = $foxyback->editTransaction($transaction_id, array('order_status_id' => $STATUS_ARRAY['Application Pending']))) {
						$this->error_info = "Error editing transaction $transaction_id: " . $foxyback->error_info;
						return NULL;
					}
				}
			}
		}

		// =================================================================
		// A transaction was edited.
		// =================================================================

		elseif ($object == 'transaction' && $event == 'EDIT') {
			$transaction_id = $object_id;
		}

		// =================================================================
		// The status was changed on a transaction.
		// =================================================================

		elseif ($object == 'transaction' && $event == 'EDIT:order_status_id') {
			$transaction_id = $object_id;

			// See what the status was changed to.
			if ($event_spec['order_status_id'] == $STATUS_ARRAY['Sent to AtLast']) {
				// Create a shipment for this transaction with AtLastFulfillment.
				$at_last_obj = new AtLast();
				if (!$create_id = $at_last_obj->createShipment($transaction_id)) {
					$this->error_info = "Error during AtLastFulfillment on transaction $transaction_id: " . $at_last_obj->error_info;
					return NULL;
				}
			}
			elseif ($event_spec['order_status_id'] == $STATUS_ARRAY['Application Approved: RESELLER']) {
				// The reseller application was approved, so add a webuser group permission to the webuser.
				$foxyback = new FoxyBack();

				if (!$transaction = $foxyback->getTransactionView($transaction_id)) {
					$this->error_info = "Error while viewing transaction $transaction_id: " . $foxyback->error_info;
					return NULL;
				}

				if (!($customer = $foxyback->getCustomerView($transaction['customer_id']))) {
					$this->error_info = "Error while fetching customer " . $transaction['customer_id'] .
					 ":" . $foxyback->error_info;
					return NULL;
				}

				if ($customer['web_user_id'] <= 0) {
					// Shouldn't happen, but if it does, run the hook to add the webuser.
					$customer_id = $transaction['customer_id'];
					if (!$this->ProcessEvent('EDIT', 'customer', $customer_id, array())) {
						$this->error_info = "Error processing hook in editCustomer ($customer_id): ".$this->error_info;
						return NULL;
					}
					// View the customer again to get the web user id.
					if (!($customer = $foxyback->getCustomerView($transaction['customer_id']))) {
						$this->error_info = "Error while fetching customer " . $transaction['customer_id'] .
						 ":" . $foxyback->error_info;
						return NULL;
					}
				}

				// Add the web user to the necessary group.
				$web_group_id = $WEB_GROUP_ARRAY['Resellers'];
				if ($web_group_id > 0) {
					$web_user_obj = new WebUser;
					if (!$group_id = $web_user_obj->addWebUserGroup($customer['web_user_id'], $web_group_id)) {
						$this->error_info = "Error while adding web user to the new group on transaction $transaction_id: " . $web_user_obj->error_info;
						return NULL;
					}
				}
			}

			// Send an email to the customer informing them of the status change.
			$notify_obj = new Notify();
			if (!$notify_obj->sendStatusMessage($transaction_id, $event_spec['order_status_id'])) {
				$this->error_info = "Error while sending status message after AtLastFulfillment on transaction $transaction_id: " . $notify_obj->error_info;
				return NULL;
			}
		}

		// =================================================================
		// Custom field added.
		// =================================================================

		elseif ($object == 'custom_field' && $event == 'ADD') {
      if ($event_spec['field_name'] == 'Update_List' &&
       $event_spec['field_value'] == 'yes') {
        $foxyback = new FoxyBack();
        $customer = $foxyback->getCustomerView($event_spec['customer_id']);

        if (!$customer) {
          $this->error_info = "Error while fetching customer ".
           $event_spec['customer_id'] .  ":" . $foxyback->error_info;
          return NULL;
        }

        $customer['confirm'] = false;
        list($customer['first_name'], $customer['last_name']) = explode(' ', $customer['fullname']);

        try {
          subscribe_user_to_list($customer, $MC_LIST_NAME, $MC_CREDENTIALS);
			
        }
        catch (Exception $err) {
          global $ERROR_ADDRESS;
          @mail($ERROR_ADDRESS, 'couldn\'t subscribe user!', serialize($event_spec)."\n\n".serialize($customer));
        }
      }
		}

		// Return a positive value to indicate success.
		return 1;
	}
	// end ProcessEvent
}

?>
